package com.hksj.Intelligentmanagement.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hksj.Intelligentmanagement.dto.CallDeviceScreenWithTaskOrderDTO;
import com.hksj.Intelligentmanagement.dto.CallTaskOrderDTO;
import com.hksj.Intelligentmanagement.dto.CallUserWithTaskOrderDTO;
import com.hksj.Intelligentmanagement.dto.DateQueryDTO;
import com.hksj.Intelligentmanagement.entity.CallTaskOrderEntity;
import com.hksj.Intelligentmanagement.mapper.CallTaskOrderMapper;
import com.hksj.Intelligentmanagement.vo.*;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class CallTaskOrderService extends ServiceImpl<CallTaskOrderMapper, CallTaskOrderEntity> {

    public final List<Integer> types = Arrays.asList(1,2);

    public Long countTaskOrder(){
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return baseMapper.countTaskOrder(dateFormat.format(new Date()));
    }

    public CallTaskOrderEntity getIncompleteOrderByOperatingRoomNo(String operatingRoomNo) {
        return baseMapper.getIncompleteOrderByOperatingRoomNo(operatingRoomNo);
    }

    public void complete(String operatingRoomNo) {
        CallTaskOrderEntity taskOrder = getIncompleteOrderByOperatingRoomNo(operatingRoomNo);
        Date now = new Date();
        taskOrder.setCompleteAt(now);
        taskOrder.setUpdateAt(now);
        taskOrder.setState(CallTaskOrderEntity.STATUS_COMPLETED);
        updateById(taskOrder);
    }

    public IPage<CallTaskOrderVo> pageTaskOrder(CallTaskOrderDTO dto) {
        Page<CallTaskOrderVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        page.addOrder(OrderItem.desc("create_at"));
        List<CallTaskOrderVo> list =  baseMapper.pageTaskOrder(page, dto);
        for (CallTaskOrderVo callTaskOrderVo : list) {
            if (callTaskOrderVo.getState() > 1){
                callTaskOrderVo.setObtainDuration(DateUtil.between(callTaskOrderVo.getCreateAt(),callTaskOrderVo.getObtainAt(), DateUnit.SECOND));
            }else{
                callTaskOrderVo.setObtainDuration(0L);
            }
            if (callTaskOrderVo.getState() == 3){
                callTaskOrderVo.setCompleteDuration(DateUtil.between(callTaskOrderVo.getObtainAt(),callTaskOrderVo.getCompleteAt(), DateUnit.MINUTE));
            }else{
                callTaskOrderVo.setCompleteDuration(0L);
            }
        }
        page.setRecords(list);
        return page;
    }

    public IPage<CallUserTaskOrderVo> pageUserTaskOrder(CallUserWithTaskOrderDTO dto) {
        Page<CallUserTaskOrderVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        List<CallUserTaskOrderVo> list = baseMapper.pageUserTaskOrder(page,dto);
        page.setRecords(list);
        return page;
    }

    public IPage<CallDeviceScreenOrderVo> pageScreenTaskOrder(CallDeviceScreenWithTaskOrderDTO dto) {
        Page<CallDeviceScreenOrderVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        List<CallDeviceScreenOrderVo> list = baseMapper.pageScreenTaskOrder(page,dto);
        page.setRecords(list);
        return page;
    }

    public List<StatisticsDispatchOrderNumVo> listDispatchOrderNum(DateQueryDTO dto) {
        return baseMapper.listDispatchOrderNum(dto);
    }

    public List<StatisticsObtainOrderNumVo> listObtainOrderNum(DateQueryDTO dto) {
        return baseMapper.listObtainOrderNum(dto);
    }

    public List<CompleteOrderNumResultVo> listDayCompleteOrderNum(DateQueryDTO dto) {
        //获取日期
        List<String> days = getDays(dto);
        //查询数据
        List<StatisticsCompleteOrderNumVo> dbDataList = baseMapper.listDayCompleteOrderNum(dto);
        List<CompleteOrderNumResultVo> resList = new ArrayList<>();

        Map<Integer, List<StatisticsCompleteOrderNumVo>> typeDataMap = new HashMap<>();
        if (!ObjectUtils.isEmpty(dbDataList)){
            typeDataMap = dbDataList.stream().collect(Collectors.groupingBy(item -> item.getType()));
        }

        for (Integer type : types) {
            List<StatisticsCompleteOrderNumVo> dayData = listDayCompleteOrderNum(days, typeDataMap.getOrDefault(type,new ArrayList<>()));
            resList.add(new CompleteOrderNumResultVo(type,dayData));
        }
        return resList;
    }

    public List<StatisticsCompleteOrderNumVo> listDayCompleteOrderNum(List<String> days, List<StatisticsCompleteOrderNumVo> dbDataList){
        Map<String, Integer> dbDataMap = dbDataList.stream()
                .filter(item -> !ObjectUtils.isEmpty(item.getNum()))
                .collect(Collectors.toMap(StatisticsCompleteOrderNumVo::getDay, StatisticsCompleteOrderNumVo::getNum));
        //拼接数据
        List<StatisticsCompleteOrderNumVo> resList = new ArrayList<>();
        for (String day : days) {
            StatisticsCompleteOrderNumVo statisticsCompleteOrderNumVo = new StatisticsCompleteOrderNumVo();
            statisticsCompleteOrderNumVo.setDay(day);
            statisticsCompleteOrderNumVo.setNum(dbDataMap.getOrDefault(day,0));
            resList.add(statisticsCompleteOrderNumVo);
        }
        return resList;
    }

    public List<CompleteOrderNumSimpleResultVo> getCompleteOrderNum(DateQueryDTO dto) {
        List<CompleteOrderNumSimpleResultVo> dbDataList = baseMapper.getCompleteOrderNum(dto);
        Map<Integer, CompleteOrderNumSimpleResultVo> typeDataMap = new HashMap<>();
        List<CompleteOrderNumSimpleResultVo> resList = new ArrayList<>();

        if (!ObjectUtils.isEmpty(dbDataList)){
            typeDataMap = dbDataList.stream().collect(Collectors.toMap(item -> item.getType(), Function.identity()));
        }
        for (Integer type : types) {
            CompleteOrderNumSimpleResultVo typeData = typeDataMap.get(type);
            resList.add(new CompleteOrderNumSimpleResultVo(type,ObjectUtils.isEmpty(typeData) ? 0 : typeData.getNum()));
        }

        return resList;
    }

    public List<ObtainDurationResultVo> listDayObtainDuration(DateQueryDTO dto) {
        //获取日期
        List<String> days = getDays(dto);
        //查询数据
        List<StatisticsObtainDurationVo> dbDataList = baseMapper.listDayObtainDuration(dto);
        List<ObtainDurationResultVo> resList = new ArrayList<>();

        Map<Integer, List<StatisticsObtainDurationVo>> typeDataMap = new HashMap<>();
        if (!ObjectUtils.isEmpty(dbDataList)){
            typeDataMap = dbDataList.stream().collect(Collectors.groupingBy(item -> item.getType()));
        }

        for (Integer type : types) {
            List<StatisticsObtainDurationVo> dayData = listDayObtainDuration(days, typeDataMap.getOrDefault(type,new ArrayList<>()));
            resList.add(new ObtainDurationResultVo(type,dayData));
        }

        return resList;
    }

    public List<StatisticsObtainDurationVo> listDayObtainDuration(List<String> days,List<StatisticsObtainDurationVo> dbDataList){
        Map<String, Double> dbDataMap = dbDataList.stream()
                .filter(item -> !ObjectUtils.isEmpty(item.getObtainDuration()))
                .collect(Collectors.toMap(StatisticsObtainDurationVo::getDay, StatisticsObtainDurationVo::getObtainDuration));
        List<StatisticsObtainDurationVo> resList = new ArrayList<>();
        for (String day : days) {
            StatisticsObtainDurationVo statisticsObtainDurationVo = new StatisticsObtainDurationVo();
            statisticsObtainDurationVo.setDay(day);
            statisticsObtainDurationVo.setObtainDuration(dbDataMap.getOrDefault(day,0D));
            resList.add(statisticsObtainDurationVo);
        }
        return resList;
    }

    public List<CompleteDurationResultVo> listDayCompleteDuration(DateQueryDTO dto) {
        //获取日期
        List<String> days = getDays(dto);
        //查询数据
        List<StatisticsCompleteDurationVo> dbDataList = baseMapper.listDayCompleteDuration(dto);
        List<CompleteDurationResultVo> resList = new ArrayList<>();

        Map<Integer, List<StatisticsCompleteDurationVo>> typeDataMap = new HashMap<>();
        if (!ObjectUtils.isEmpty(dbDataList)){
            typeDataMap = dbDataList.stream().collect(Collectors.groupingBy(item -> item.getType()));
        }

        for (Integer type : types) {
            List<StatisticsCompleteDurationVo> typeData = listDayCompleteDuration(days, typeDataMap.getOrDefault(type,new ArrayList<>()));
            resList.add(new CompleteDurationResultVo(type,typeData));
        }
        return resList;
    }

    public List<StatisticsCompleteDurationVo> listDayCompleteDuration(List<String> days,List<StatisticsCompleteDurationVo> dbDataList){
        Map<String, Double> dbDataMap = dbDataList.stream()
                .filter(item -> !ObjectUtils.isEmpty(item.getCompleteDuration()))
                .collect(Collectors.toMap(StatisticsCompleteDurationVo::getDay, StatisticsCompleteDurationVo::getCompleteDuration));
        List<StatisticsCompleteDurationVo> resList = new ArrayList<>();
        for (String day : days) {
            StatisticsCompleteDurationVo statisticsCompleteDurationVo = new StatisticsCompleteDurationVo();
            statisticsCompleteDurationVo.setDay(day);
            statisticsCompleteDurationVo.setCompleteDuration(dbDataMap.getOrDefault(day,0D));
            resList.add(statisticsCompleteDurationVo);
        }
        return resList;
    }

    public StatisticsInfoVo getStatisticsInfo() {
        return  baseMapper.getStatisticsInfo();
    }


    private List<String> getDays(DateQueryDTO dto){
        List<DateTime> dateTimes = DateUtil.rangeToList(DateUtil.offsetDay(DateUtil.parseDateTime(dto.getStartAt()),1), DateUtil.parseDateTime(dto.getEndAt()), DateField.DAY_OF_MONTH);
        List<String> days = new ArrayList<>();
        for (DateTime day : dateTimes) {
            days.add(DateUtil.format(day,"yyyy-MM-dd"));
        }
        return days;
    }
}
